package com.core.aspect;

import com.alibaba.fastjson2.JSON;
import com.core.domain.Permissions;
import com.core.service.OperationLogService;
import com.core.annotation.OperationLog;
import com.core.domain.OperationLogs;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import com.core.dto.UserDetailsDto;
import com.core.service.PermissionsService;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

@Slf4j
@Aspect
@Component
public class OperationLogAspect {

    @Autowired
    private OperationLogService operationLogService;

    @Autowired
    private PermissionsService permissionsService;

    @Pointcut("@annotation(com.core.annotation.OperationLog)")
    public void operationLogPointcut() {}

    @Around("operationLogPointcut()")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long beginTime = System.currentTimeMillis();
        Object result = point.proceed();
        long time = System.currentTimeMillis() - beginTime;
        recordLog(point, time);
        return result;
    }

    private void recordLog(ProceedingJoinPoint point, long time) {
        try {
            MethodSignature signature = (MethodSignature) point.getSignature();
            Method method = signature.getMethod();
            OperationLog annotation = method.getAnnotation(OperationLog.class);
            
            // 获取当前登录用户
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            Long userId = null;
            String username = "anonymous";
            if (authentication != null && authentication.getPrincipal() instanceof UserDetailsDto) {
                UserDetailsDto userDetails = (UserDetailsDto) authentication.getPrincipal();
                userId = userDetails.getUser().getUserId();
                username = userDetails.getUsername();
            }
            
            // 获取权限ID
            Long permissionId = getPermissionId(annotation.type(), annotation.module());

            // 获取请求信息
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            HttpServletRequest request = attributes != null ? attributes.getRequest() : null;
            
            // 构建日志对象
            OperationLogs logEntry = new OperationLogs();
            logEntry.setUserId(userId); // 设置用户ID
            logEntry.setPermissionId(permissionId); // 设置权限ID
            logEntry.setOperationType(annotation.type());
            logEntry.setModule(annotation.module());
            logEntry.setDescription(parseDescription(annotation.description(), point.getArgs()));
            logEntry.setOperationTime(LocalDateTime.now());
            
            // 记录日志
            operationLogService.save(logEntry);
            
            log.info("操作日志记录成功 - 用户: {}, 操作: {}, 耗时: {}ms", 
                    username, annotation.type(), time);
        } catch (Exception e) {
            log.error("记录操作日志失败", e);
        }
    }

    /**
     * 根据操作类型和模块查找权限ID
     */
    private Long getPermissionId(String operationType, String module) {
        if (operationType == null || operationType.isEmpty() || module == null || module.isEmpty()) {
            return null;
        }
        String permissionName = module + ":" + operationType; // 构建权限名称
        Permissions permission = permissionsService.getPermissionByName(permissionName);
        return permission != null ? permission.getId() : null;
    }

    private String parseDescription(String description, Object[] args) {
        if (description == null || description.isEmpty()) {
            return "";
        }
        
        try {
            // 替换描述中的参数占位符
            for (int i = 0; i < args.length; i++) {
                description = description.replace("#" + i, args[i] != null ? args[i].toString() : "null");
            }
            
            // 处理特殊格式的参数，如 #user.username
            if (description.contains("#")) {
                for (Object arg : args) {
                    if (arg != null) {
                        String argStr = JSON.toJSONString(arg);
                        // Simplified regex for demonstration, adjust as needed
                        description = description.replaceAll("#\\w+\\.[a-zA-Z]+", argStr);
                    }
                }
            }
            
            return description;
        } catch (Exception e) {
            log.error("解析操作日志描述失败", e);
            return description;
        }
    }
} 